// 定义 Promise.all 方法
Promise.all = function (iterable) {
  // 返回一个新的 Promise 对象
  return new Promise((resolve, reject) => {
    // 如果参数不是可迭代对象，就抛出错误
    if (!iterable[Symbol.iterator]) {
      throw new TypeError("argument must be iterable");
    }
    // 将参数转换为数组
    let array = Array.from(iterable);
    // 获取数组的长度
    let length = array.length;
    // 如果数组为空，就直接成功
    if (length === 0) {
      resolve([]);
      return;
    }
    // 定义一个计数器，记录成功的次数
    let count = 0;
    // 定义一个结果数组，存放成功的值
    let result = [];
    // 遍历数组中的每个元素
    for (let i = 0; i < length; i++) {
      // 获取当前元素
      let value = array[i];
      // 如果是 Promise 对象，就调用 then 方法
      if (value instanceof Promise) {
        value.then(
          (res) => {
            // 将成功的值按照顺序存入结果数组
            result[i] = res;
            // 计数器加一
            count++;
            // 如果计数器等于数组长度，就说明所有的 Promise 都成功了
            if (count === length) {
              // 将结果数组作为成功值传给新的 Promise 的 resolve 函数
              resolve(result);
            }
          },
          (err) => {
            // 如果有一个 Promise 失败了，就把失败原因传给新的 Promise 的 reject 函数
            reject(err);
          }
        );
      } else {
        // 如果不是 Promise 对象，就直接当作成功值处理
        result[i] = value;
        count++;
        if (count === length) {
          resolve(result);
        }
      }
    }
  });
};

function pAll(_promises) {
  return new Promise((resolve, reject) => {
    // Iterable => Array
    const promises = Array.from(_promises);
    // 结果用一个数组维护
    const r = [];
    const len = promises.length;
    let count = 0;
    for (let i = 0; i < len; i++) {
      // Promise.resolve 确保把所有数据都转化为 Promise
      Promise.resolve(promises[i])
        .then((o) => {
          // 因为 promise 是异步的，保持数组一一对应
          r[i] = o;

          // 如果数组中所有 promise 都完成，则返回结果数组
          if (++count === len) {
            resolve(r);
          }
          // 当发生异常时，直接 reject
        })
        .catch((e) => reject(e));
    }
  });
}

const _promisesAll = (promises) => {
  return Promise.new((resolve, reject) => {
    let rs = [];
    let count = 0;
    for (let i = 0; i < promises.length; i++) {
      let p = promises[i];
      Promise.resolve(p)
        .then((res) => {
          rs[i] = res;
          if (++count === promises.length) {
            resolve(rs);
          }
        })
        .catch((err) => {
          reject(err);
        });
    }
  });
};
